import { defineComponent, onMounted, onUnmounted, ref } from "vue";
import { getComponentsMap } from "../schema/components";
import { useLayoutStore } from "../store/index";
import EventBus from "../util/event";

export default defineComponent({
  props: ["item"],
  emits: ["ShowHelpLine"],
  setup(props, ctx) {
    let componentMap = getComponentsMap();
    let layoutStore = useLayoutStore();
    let itemRef = ref<any>(null);
    let dragLeft: number, dargTop: number;
    let helpLeftToRightLines: any[] = [];
    let helpTopToBotomLines: any[] = [];

    const initLines = () => {
      let currentWidth = props.item.position.width;
      let currentHeight = props.item.position.height;
      helpLeftToRightLines = [
        {
          show: layoutStore.getStyle.width / 2,
          left: layoutStore.getStyle.width / 2 - currentWidth / 2,
        },
      ];
      helpTopToBotomLines = [
        {
          show: layoutStore.getStyle.height / 2,
          top: layoutStore.getStyle.height / 2 - currentHeight / 2,
        },
      ];
      layoutStore.getComponents
        .filter((item: any) => item.uuid !== props.item.uuid)
        .forEach((component: any) => {
          let p = component.position;
          let l = p.left;
          let t = p.top;
          helpLeftToRightLines.push({ show: l, left: l }); //左对左
          helpLeftToRightLines.push({ show: l, left: l - currentWidth }); //右对左
          helpLeftToRightLines.push({
            show: l + p.width / 2,
            left: l + p.width / 2 - currentWidth / 2,
          }); //中对中
          helpLeftToRightLines.push({ show: l + p.width, left: l + p.width }); //左对右
          helpLeftToRightLines.push({
            show: l + p.width,
            left: l + p.width - currentWidth,
          }); //右对右

          helpTopToBotomLines.push({ show: t, top: t });
          helpTopToBotomLines.push({ show: t, top: t - currentHeight });
          helpTopToBotomLines.push({
            show: t + p.height / 2,
            top: t + p.height / 2 - currentHeight / 2,
          });
          helpTopToBotomLines.push({
            show: t + p.height,
            top: t + p.height - currentHeight,
          });
          helpTopToBotomLines.push({ show: t + p.height, top: t + p.height });
        });
    };

    const computeLines = (l: number, t: number, e: DragEvent) => {
      let targetLeft: any = null;
      let targetTop: any = null;
      for (let i = 0; i < helpLeftToRightLines.length; i++) {
        if (Math.abs(l - helpLeftToRightLines[i].left) < 5) {
          targetLeft = {
            leftLine: helpLeftToRightLines[i].show,
            left: helpLeftToRightLines[i].left,
          };
          break;
        }
      }

      for (let i = 0; i < helpTopToBotomLines.length; i++) {
        if (Math.abs(t - helpTopToBotomLines[i].top) < 5) {
          targetTop = {
            topLine: helpTopToBotomLines[i].show,
            top: helpTopToBotomLines[i].top,
          };
          break;
        }
      }

      ctx.emit("ShowHelpLine", {
        left: targetLeft === null ? -1 : targetLeft.leftLine,
        top: targetTop === null ? -1 : targetTop.topLine,
      });

      dragLeft = targetLeft !== null ? targetLeft.left : -1;
      dargTop = targetTop != null ? targetTop.top : -1;
    };

    onMounted(() => {
      props.item.position.width = itemRef.value.offsetWidth;
      props.item.position.height = itemRef.value.offsetHeight;
      itemRef.value.addEventListener("dragstart", itemDragStart);
    });

    onUnmounted(() => {
      itemRef.value?.removeEventListener("dragstart", itemDragStart);
    });

    let x: number, y: number;

    let itemDragStart = (e: DragEvent) => {
      EventBus.emit("before-record");
      initLines();
      x = e.clientX;
      y = e.clientY;
      itemRef.value.addEventListener("drag", itemDrag);
      itemRef.value.addEventListener("dragend", itemDragEnd);
    };

    let itemDrag = (e: DragEvent) => {
      if (e.clientX !== 0 && e.clientY !== 0) {
        props.item.position.left = props.item.position.left + e.clientX - x;
        props.item.position.top = props.item.position.top + e.clientY - y;
        x = e.clientX;
        y = e.clientY;
        computeLines(props.item.position.left, props.item.position.top, e);
      }
    };

    let itemDragEnd = (e: DragEvent) => {
      if (dragLeft >= 0) {
        props.item.position.left = dragLeft;
      } else {
        if (props.item.position.left < 0) {
          props.item.position.left = 0;
        } else if (
          props.item.position.left >
          layoutStore.getStyle.width - props.item.position.width
        ) {
          props.item.position.left =
            layoutStore.getStyle.width - props.item.position.width;
        }
      }

      if (dargTop >= 0) {
        props.item.position.top = dargTop;
      } else {
        if (props.item.position.top < 0) {
          props.item.position.top = 0;
        } else if (
          props.item.position.top >
          layoutStore.getStyle.height - props.item.position.height
        ) {
          props.item.position.top =
            layoutStore.getStyle.height - props.item.position.height;
        }
      }

      itemRef.value.removeEventListener("drag", itemDrag);
      itemRef.value.removeEventListener("dragend", itemDragEnd);
      ctx.emit("ShowHelpLine", { left: -1, top: -1 });
      EventBus.emit("after-record");
    };

    let ItemClick = (e: any) => {
      layoutStore.getComponents.forEach((com: any) => {
        if (com.uuid === props.item.uuid) {
          com.selected = !com.selected;
        } else {
          com.selected = false;
        }
      });
    };

    return () => {
      return (
        <div
          class="canve-item"
          id={props.item.uuid}
          onClick={ItemClick}
          draggable
          ref={itemRef}
          style={{
            left: props.item.position.left + "px",
            top: props.item.position.top + "px",
            position: "absolute",
            borderColor: props.item.selected ? "red" : "greenyellow",
          }}
        >
          {componentMap
            .get(props.item.component)
            .render(props.item && props.item.props ? props.item.props : null)}
        </div>
      );
    };
  },
});
